﻿using EFFC.Frame.Net.Module.Extend.EWRA.Attributes;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using EFFC.Extends.LinqDLR2SQL;
using EFFC.Frame.Net.Unit.DB;
using EFFC.Frame.Net.Base.Data.Base;
using EFFC.Frame.Net.Module.Extend.EWRA.Attributes.Validation;
using EFFC.Frame.Net.Base.Common;
using EFFC.Frame.Net.Base.Data;
using EFFC.Frame.Net.Module.Business.Datas;
using ICPFrameLib.Business;
using ICPFrameLib.Attributes;

namespace XHRPMIS.Business.v1._0
{
    public class DynamicFunc : MyRestLogic
    {
        //可以作为search的栏位类型
        static string[] search_support_date_type = new string[] { "varchar", "nvarchar", "int", "numberic", "datetime", "bit" };
        [EWRARouteDesc("获取动态功能设定列表")]
        [EWRAOutputDesc("返回结果", @"[{
    uid:'uid',
    name:'单表操作-介绍名称',
    desc:'单表操作-描述',
    action_auth:'功能Action授权设定,对应于功能管理中的“访问授权码”',
    meta_uid:'关联的元数据表的UID',
    meta_name:'关联的元数据表的名称',
    meta_desc:'关联的元数据表的中文名称',
}]")]
        public override List<object> get()
        {
            SetCacheEnable(false);
            var up = DB.NewMetaUnitParameter();
            var s = from t in DB.LamdaTable(up, "EXTEND_SINGLETABLE_OP", "a")
                    join t2 in DB.LamdaTable(up, "EXTEND_METADATA", "b").LeftJoin() on t.MetaUID equals t2.MetaUID
                    select new
                    {
                        uid = t.S_UID,
                        name = t.S_Name,
                        desc = t.S_Desc,
                        action_auth = t.ActionAuth,
                        meta_uid = t.MetaUID,
                        meta_name = t2.MetaName,
                        meta_desc = t2.MetaDesc
                    };

            return s.GetQueryList(up).ToList<object>();
        }
        [EWRARouteDesc("获取指定的动态功能设定")]
        [EWRAAddInput("id", "string", "uid", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.Path, false)]
        [EWRAOutputDesc("返回结果", @"{
code:'success-成功，failed-失败',
msg:'提示信息',
data:{
        uid:'uid',
        name:'单表操作-介绍名称',
        desc:'单表操作-描述',
        action_auth:'功能Action授权设定,对应于功能管理中的“访问授权码”',
        meta_uid:'关联的元数据表的UID',
        meta_name:'关联的元数据表的名称',
        meta_desc:'关联的元数据表的中文名称',
        search:[
            {
                search_id:'查询条件组编号',
                search_desc:'查询条件组描述',
                tips:'查询条件组标签提示说明',
                is_required:'必输检查标记，界面针对该标记显示必输标记',
                sort_num:'排序编号',
                memo:'备注',
                conditions:[
                    {
                        condition_id:'条件编号',
                        op:'查询条件操作方式，受元数据栏位的设定影响，可以使用的操作方式是受限的',
                        column_name:'栏位名称',
                        parameter_name:'相关的参数名称,做查询条件时页面传入的参数名称',
                        tips:'提示说明',
                        check_required:'必输检查',
                        check_regex:'正则表达式检查'
                    }
                ]
            }
        ],
        columns:[
            {
                column_name:'栏位名称',
                column_desc:'表头名称',
                max_length:'允许输入的最大长度',
                tips:'标签提示说明',
                check_required:'必输检查',
                check_regex:'正则表达式检查',
                sort_num:'排序编号',
                memo:'备注'
            }
        ],
        events:[{
            no:'事件编号',
            name:'事件名称',
            category:'事件分类，相关说明参见《事件扩展设计说明.docx》',
            type:'事件类型，相关说明参见《事件扩展设计说明.docx》',
            at:'事件触发时机，相关说明参见《事件扩展设计说明.docx》',
            desc:'事件描述'
        }],
        row_events:[{
            no:'事件编号',
            name:'事件名称',
            category:'事件分类，相关说明参见《事件扩展设计说明.docx》',
            type:'事件类型，相关说明参见《事件扩展设计说明.docx》',
            at:'事件触发时机，相关说明参见《事件扩展设计说明.docx》',
            desc:'事件描述'
        }]
    }
}")]
        public override object get(string id)
        {
            SetCacheEnable(false);
            var up = DB.NewMetaUnitParameter();
            var s = from t in DB.LamdaTable(up, "EXTEND_SINGLETABLE_OP", "a")
                    where (t.s_uid == id || t.S_Name == id)
                    select t;
            var list = s.GetQueryList(up);
            if (list.Count <= 0)
            {
                return new
                {
                    code = "failed",
                    msg = "设定资料不存在"
                };
            }

            dynamic info = list.First();
            string metauid = info.MetaUID;
            var meta_name = "";
            var meta_desc = "";
            var metalist = (from t in DB.LamdaTable(up, "EXTEND_METADATA", "a")
                            where t.metauid == metauid
                            select t).GetQueryList(up);
            if (metalist.Count > 0)
            {
                meta_name = ComFunc.nvl(metalist.First().GetValue("MetaName"));
                meta_desc = ComFunc.nvl(metalist.First().GetValue("MetaDesc"));
            }

            //抓取设定的条件列表
            var searchlist = (from t in DB.LamdaTable(up, "EXTEND_SINGLETABLE_OP_SEARCH", "a")
                              orderby t.S_Sort_Num
                              where t.S_UID == info.S_UID
                              select new
                              {
                                  search_id = t.S_SearchID,
                                  search_desc = t.S_SearchDesc,
                                  tips = t.S_Tips,
                                  is_required = t.S_IsRequired,
                                  memo = t.S_Memo,
                                  sort_num = t.S_Sort_Num
                              }).GetQueryList(up);
            var condition_s = from t in DB.LamdaTable(up, "EXTEND_SINGLETABLE_OP_CONDITIONS", "a")
                              join t2 in DB.LamdaTable(up, "EXTEND_METADATA_COLUMNS", "b").LeftJoin() on t.S_ColumnName equals t2.MetaColumnName
                              join t3 in DB.LamdaTable(up, "EXTEND_METADATA_DATATYPE", "c").LeftJoin() on t2.MetaDataType equals t3.DataType
                              where t.S_UID == info.S_UID && t2.MetaUID == info.MetaUID
                              select new
                              {
                                  search_id = t.S_SearchID,
                                  condition_id = t.S_ConditionID,
                                  op = t.S_ConditionOP,
                                  column_name = t.S_ColumnName,
                                  parameter_name = t.S_Parameter,
                                  tips = t.S_Tips,
                                  check_required = t.S_Check_Required,
                                  check_regex = t.S_Check_Regex,
                                  data_type = t2.MetaDataType,
                                  reference = t2.MetaReference,
                                  is_allow_empty = t2.MetaAllowEmpty,
                                  default_ui_type = t3.UI_TYPE
                              };
            var conditionlist = condition_s.GetQueryList(up);
            var search = from t in searchlist
                         select new
                         {
                             t.search_id,
                             t.search_desc,
                             t.tips,
                             is_required = BoolStd.IsNotBoolThen(t.is_required, false),
                             t.memo,
                             t.sort_num,
                             conditions = conditionlist.Where(w => w.search_id == t.search_id)
                                        .Select((d) =>
                                        {
                                            return new
                                            {
                                                d.condition_id,
                                                d.op,
                                                d.column_name,
                                                d.parameter_name,
                                                d.tips,
                                                check_required = BoolStd.IsNotBoolThen(d.check_required, false),
                                                d.check_regex

                                            };
                                        })
                         };
            //抓取显示栏位设定
            var columnlist = (from t in DB.LamdaTable(up, "EXTEND_SINGLETABLE_OP_COLUMNS", "a")
                              orderby t.S_Sort_Num
                              where t.S_UID == info.S_UID
                              select new
                              {
                                  column_name = t.S_ColumnName,
                                  column_desc = t.S_ColumnDesc,
                                  max_length = t.S_ColumnMaxSize,
                                  tips = t.S_Tips,
                                  check_required = t.S_Check_Required,
                                  check_regex = t.S_Check_Regex,
                                  sort_num = t.S_Sort_Num,
                                  memo = t.S_Memo
                              }).GetQueryList(up);
            var columns = from t in columnlist
                          select new
                          {
                              t.column_name,
                              t.column_desc,
                              max_length = IntStd.IsNotIntThen(t.max_length, -1),
                              t.tips,
                              check_required = BoolStd.IsNotBoolThen(t.check_required, false),
                              t.check_regex,
                              t.memo,
                              t.sort_num
                          };
            //获取事件信息
            var eventslist = (from t in DB.LamdaTable(up, "EXTEND_EVENTS", "a")
                              join t2 in DB.LamdaTable(up, "EXTEND_SINGLETABLE_OP_EVENTS", "b") on t.EventNo equals t2.S_Event_No
                              where t2.S_UID == info.S_UID
                              select new
                              {
                                  no = t.EventNo,
                                  name = t.EventName,
                                  category = t.EventCategory,
                                  type = t.EventType,
                                  at = t.EventAt,
                                  desc = t.EventDesc
                              }).GetQueryList(up);
            return new
            {
                code = "success",
                msg = "",
                name = info.S_Name,
                desc = info.S_Desc,
                action_auth = info.ActionAuth,
                meta_uid = info.MetaUID,
                meta_name,
                meta_desc,
                search,
                columns,
                events = eventslist.Where(w => !ComFunc.nvl(w.type).StartsWith("Row")),
                row_events = eventslist.Where(w => ComFunc.nvl(w.type).StartsWith("Row"))
            };
        }
        [EWRAEmptyValid("name")]
        [EWRARouteDesc("新增一个动态功能设定")]
        [EWRAAddInput("name", "string", "动态设定的名称", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, false)]
        [EWRAAddInput("desc", "string", "动态设定的描述", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, true)]
        [EWRAOutputDesc("返回结果", @"{
code:'success-成功，failed-失败',
msg:'提示信息',
uid:'创建成功返回的uid'
}")]
        public override object post()
        {
            var name = ComFunc.nvl(PostDataD.name);
            var desc = ComFunc.nvl(PostDataD.desc);
            var up = DB.NewMetaUnitParameter();
            if ((from t in DB.LamdaTable(up, "EXTEND_SINGLETABLE_OP", "a")
                 where t.S_Name == name
                 select t).IsExists(up))
            {
                return new
                {
                    code = "failed",
                    msg = "名称已经存在"
                };
            }
            var uid = Guid.NewGuid().ToString();
            DB.QuickInsert(up, "EXTEND_SINGLETABLE_OP", new
            {
                S_UID = uid,
                S_Name = name,
                S_Desc = desc,
                add_id = TokenPayLoad.ID,
                add_ip = ClientInfo.IP,
                add_name = TokenPayLoad["username"],
                add_time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
                last_id = TokenPayLoad.ID,
                last_ip = ClientInfo.IP,
                last_name = TokenPayLoad["username"],
                last_time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
            });
            return new
            {
                code = "success",
                msg = "操作成功",
                uid
            };
        }
        [EWRARouteDesc("删除一个动态功能设定")]
        [EWRAAddInput("id", "string", "动态功能uid", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.Path, false)]
        public override bool delete(string id)
        {
            BeginTrans();
            var up = DB.NewMetaUnitParameter();
            var s = from t in DB.LamdaTable(up, "EXTEND_SINGLETABLE_OP", "a")
                    where (t.s_uid == id || t.S_Name == id)
                    select t;
            var list = s.GetQueryList(up);
            if (list.Count <= 0)
            {
                return false;
            }

            dynamic info = list.First();
            DB.QuickDelete(up, "EXTEND_SINGLETABLE_OP_COLUMNS", new
            {
                S_UID = info.S_UID
            });
            DB.QuickDelete(up, "EXTEND_SINGLETABLE_OP_CONDITIONS", new
            {
                S_UID = info.S_UID
            });
            DB.QuickDelete(up, "EXTEND_SINGLETABLE_OP_SEARCH", new
            {
                S_UID = info.S_UID
            });
            DB.QuickDelete(up, "EXTEND_SINGLETABLE_OP", new
            {
                S_UID = info.S_UID
            });
            DB.QuickDelete(up, "EXTEND_SINGLETABLE_OP_EVENTS", new
            {
                S_UID = info.S_UID
            });
            CommitTrans();
            return true;
        }
        [EWRAEmptyValid("data")]
        [EWRARouteDesc("修改一个动态功能设定")]
        [EWRAAddInput("id", "string", "动态功能uid", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.Path, false)]
        [EWRAAddInput("data", "string", @"待修改的数据，先采用URLcode编码，然后采用base64编码，数据的格式如下：{
        name:'单表操作-介绍名称',
        desc:'单表操作-描述',
        action_auth:'功能Action授权设定,对应于功能管理中的“访问授权码”',
        meta_uid:'关联的元数据表的UID',
        search:[
            {
                search_id:'查询条件组编号,没有则给空',
                search_desc:'查询条件组描述',
                tips:'查询条件组标签提示说明',
                is_required:'必输检查标记，界面针对该标记显示必输标记',
                memo:'备注',
                sort_num:'排序编号',
                conditions:[
                    {
                        condition_id:'条件编号,没有则给空',
                        op:'查询条件操作方式：like-模糊查询，=-精确查询，>-大于,>=-大于等于，<-小于，<=-小于等于',
                        column_name:'栏位名称',
                        parameter_name:'相关的参数名称,做查询条件时页面传入的参数名称',
                        tips:'提示说明',
                        check_required:'必输检查',
                        check_regex:'正则表达式检查'
                    }
                ]
            }
        ],
        columns:[
            {
                column_name:'栏位名称',
                column_desc:'表头名称',
                max_length:'允许输入的最大长度，为空或负数时则不做限定',
                tips:'标签提示说明',
                check_required:'必输检查',
                check_regex:'正则表达式检查',
                sort_num:'排序编号',
                memo:'备注'
            }
        ],
        events:[{
            no:'事件编号',
            name:'事件名称',
            category:'事件分类，相关说明参见《事件扩展设计说明.docx》',
            type:'事件类型，相关说明参见《事件扩展设计说明.docx》'
        }],
        row_events:[{
            no:'事件编号',
            name:'事件名称',
            category:'事件分类，相关说明参见《事件扩展设计说明.docx》',
            type:'事件类型，相关说明参见《事件扩展设计说明.docx》'
        }]
    }", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, false)]
        [EWRAOutputDesc("返回结果", @"{
code:'success-成功，failed-失败',
msg:'提示信息',
uid:'创建成功返回的uid'
}")]
        public override object patch(string id)
        {
            #region 检核
            var str = ComFunc.UrlDecode(ComFunc.IsBase64Then(ComFunc.nvl(PostDataD.data).Replace(" ", "+")));
            if (str == "")
            {
                return new
                {
                    code = "failed",
                    msg = "数据格式不正确"
                };
            }
            var data = FrameDLRObject.IsJsonThen(str);
            if (data == null)
            {
                return new
                {
                    code = "failed",
                    msg = "数据格式不正确"
                };
            }
            if (ComFunc.nvl(data.name) == "")
            {
                return new
                {
                    code = "failed",
                    msg = "名称不能为空"
                };
            }
            BeginTrans();
            var up = DB.NewMetaUnitParameter();
            var s = from t in DB.LamdaTable(up, "EXTEND_SINGLETABLE_OP", "a")
                    where (t.s_uid == id || t.S_Name == id)
                    select t;
            var list = s.GetQueryList(up);
            if (list.Count <= 0)
            {
                return new
                {
                    code = "failed",
                    msg = "设定资料不存在"
                };
            }


            dynamic info = list.First();
            if ((from t in DB.LamdaTable(up, "EXTEND_SINGLETABLE_OP", "a")
                 where t.s_uid != info.s_uid && t.s_name == data.name
                 select t).IsExists(up))
            {
                return new
                {
                    code = "failed",
                    msg = "存在同名的设定"
                };
            }


            if (ComFunc.nvl(data.meta_uid) != "")
            {
                string metauid = ComFunc.nvl(data.meta_uid);
                var metalist = (from t in DB.LamdaTable(up, "EXTEND_METADATA", "a")
                                where t.metauid == metauid
                                select t).GetQueryList(up);
                if (metalist.Count <= 0)
                {
                    return new
                    {
                        code = "failed",
                        msg = "关联的元数据表不存在"
                    };
                }
                if (metalist.Where(w => BoolStd.IsNotBoolThen(w.IsCreated, false)).Count() <= 0)
                {
                    return new
                    {
                        code = "failed",
                        msg = $"关联的元数据表未建表，建议到元数据表中完成表的创建,表名为：{metalist.First().GetValue("MetaDesc")}({metalist.First().GetValue("MetaDesc")})"
                    };
                }
            }
            //search项目的检查
            IEnumerable<object> search = data.search;
            var condition_columns = "";
            if (search != null)
            {
                foreach (dynamic item in search)
                {
                    IEnumerable<object> conditions = item.conditions;
                    if (conditions == null || conditions.Count() <= 0)
                    {
                        return new
                        {
                            code = "failed",
                            msg = "当设定了查询组时，相关的查询条件必须设定"
                        };
                    }
                    foreach (dynamic citem in conditions)
                    {
                        condition_columns += $"{citem.column_name},";
                    }
                }
            }
            //栏位的检查
            IEnumerable<object> columns = data.columns;
            var columns_str = "";
            if (columns != null)
            {
                foreach (dynamic item in columns)
                {
                    if (ComFunc.nvl(item.column_name) == "")
                    {
                        return new
                        {
                            code = "failed",
                            msg = "栏位名称不可为空"
                        };
                    }
                    columns_str += $"{item.column_name},";
                }
            }
            //事件检查
            IEnumerable<object> events = data.events;
            IEnumerable<object> row_events = data.row_events;
            var eventslist = (from t in DB.LamdaTable(up, "EXTEND_EVENTS", "a")
                        where t.EventCategory == "Customerize"
                        select new
                        {
                            no = t.EventNo,
                            name = t.EventName,
                            category = t.EventCategory,
                            type = t.EventType,
                            at = t.EventAt,
                            desc = t.EventDesc
                        }).GetQueryList(up);
            var event_nos = eventslist.Select(d => (string)ComFunc.nvl(d.GetValue("no"))).ToArray();
            var update_events = new List<object>();
            if (events != null)
            {
                foreach (dynamic item in events)
                {
                    if (event_nos.Contains((string)ComFunc.nvl(item.no)))
                    {
                        update_events.Add(new
                        {
                            S_UID = info.s_uid,
                            S_Event_No = item.no
                        });
                    }
                }
            }
            if (row_events != null)
            {
                foreach (dynamic item in row_events)
                {
                    if (event_nos.Contains((string)ComFunc.nvl(item.no)))
                    {
                        update_events.Add(new
                        {
                            S_UID = info.s_uid,
                            S_Event_No = item.no
                        });
                    }
                }
            }
            //执行元数据与栏位匹配检查
            var meta_columns = (from t in DB.LamdaTable(up, "EXTEND_METADATA_COLUMNS", "a")
                                where t.MetaUID == data.meta_uid
                                select new
                                {
                                    column_name = t.MetaColumnName
                                }).GetQueryList(up);
            var meta_columns_arr = meta_columns.Select((d) => { FrameDLRObject dobj = d; return ComFunc.nvl(dobj.GetValue("column_name")); }).ToArray();
            if (condition_columns != "")
            {
                if (condition_columns.Split(",", StringSplitOptions.RemoveEmptyEntries).Where(w => !meta_columns_arr.Contains(w)).Count() > 0)
                {
                    return new
                    {
                        code = "failed",
                        msg = $"查询条件绑定的栏位不属于所选的元数据表"
                    };
                }
                if (columns_str.Split(",", StringSplitOptions.RemoveEmptyEntries).Where(w => !meta_columns_arr.Contains(w)).Count() > 0)
                {
                    return new
                    {
                        code = "failed",
                        msg = $"栏位不属于所选的元数据表"
                    };
                }
            }
            #endregion
            #region 更新EXTEND_SINGLETABLE_OP
            DB.QuickUpdate(up, "EXTEND_SINGLETABLE_OP", new
            {
                S_Name = data.name,
                S_Desc = data.desc,
                ActionAuth = data.action_auth,
                MetaUID = data.meta_uid,
                last_id = TokenPayLoad.ID,
                last_ip = ClientInfo.IP,
                last_name = TokenPayLoad["username"],
                last_time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
            }, new
            {
                S_UID = info.s_uid
            });
            #endregion
            #region 先删除相关子表的设定
            DB.QuickDelete(up, "EXTEND_SINGLETABLE_OP_SEARCH", new
            {
                S_UID = info.s_uid
            });
            DB.QuickDelete(up, "EXTEND_SINGLETABLE_OP_CONDITIONS", new
            {
                S_UID = info.s_uid
            });
            DB.QuickDelete(up, "EXTEND_SINGLETABLE_OP_COLUMNS", new
            {
                S_UID = info.s_uid
            });
            DB.QuickDelete(up, "EXTEND_SINGLETABLE_OP_EVENTS", new
            {
                S_UID = info.s_uid
            });
            #endregion
            #region Search新增
            if (search != null)
            {
                foreach (dynamic item in search)
                {
                    var search_uid = ComFunc.nvl(item.search_id) == "" ? Guid.NewGuid().ToString() : ComFunc.nvl(item.search_id);
                    DB.QuickInsert(up, "EXTEND_SINGLETABLE_OP_SEARCH", new
                    {
                        S_UID = info.s_uid,
                        S_SearchID = search_uid,
                        S_SearchDesc = item.search_desc,
                        S_Tips = item.tips,
                        S_IsRequired = BoolStd.ConvertTo(item.is_required, 1, 0),
                        S_Memo = item.memo,
                        S_Sort_Num = IntStd.IsNotIntThen(item.sort_num),
                        add_id = TokenPayLoad.ID,
                        add_ip = ClientInfo.IP,
                        add_name = TokenPayLoad["username"],
                        add_time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
                        last_id = TokenPayLoad.ID,
                        last_ip = ClientInfo.IP,
                        last_name = TokenPayLoad["username"],
                        last_time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
                    });
                    IEnumerable<object> conditions = item.conditions;
                    foreach (dynamic citem in conditions)
                    {
                        var condition_uid = ComFunc.nvl(item.condition_id) == "" ? Guid.NewGuid().ToString() : ComFunc.nvl(item.condition_id);
                        DB.QuickInsert(up, "EXTEND_SINGLETABLE_OP_CONDITIONS", new
                        {
                            S_UID = info.s_uid,
                            S_SearchID = search_uid,
                            S_ConditionID = condition_uid,
                            S_ConditionOP = citem.op,
                            S_ColumnName = citem.column_name,
                            S_Parameter = citem.parameter_name,
                            S_Tips = citem.tips,
                            S_Check_Required = BoolStd.ConvertTo(citem.check_required, 1, 0),
                            S_Check_Regex = citem.check_regex,
                            add_id = TokenPayLoad.ID,
                            add_ip = ClientInfo.IP,
                            add_name = TokenPayLoad["username"],
                            add_time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
                            last_id = TokenPayLoad.ID,
                            last_ip = ClientInfo.IP,
                            last_name = TokenPayLoad["username"],
                            last_time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
                        });
                    }
                }
            }
            #endregion
            #region column新增
            if (columns != null)
            {
                foreach (dynamic item in columns)
                {
                    var condition_uid = ComFunc.nvl(item.condition_id) == "" ? Guid.NewGuid().ToString() : ComFunc.nvl(item.condition_id);
                    DB.QuickInsert(up, "EXTEND_SINGLETABLE_OP_COLUMNS", new
                    {
                        S_UID = info.s_uid,
                        S_ColumnName = item.column_name,
                        S_ColumnDesc = item.column_desc,
                        S_ColumnMaxSize = IntStd.IsNotIntThen(item.max_length, -1),
                        S_Tips = item.tips,
                        S_Check_Required = BoolStd.ConvertTo(item.check_required, 1, 0),
                        S_Check_Regex = item.check_regex,
                        S_Sort_Num = IntStd.IsNotIntThen(item.sort_num),
                        S_Memo = item.memo,
                        add_id = TokenPayLoad.ID,
                        add_ip = ClientInfo.IP,
                        add_name = TokenPayLoad["username"],
                        add_time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
                        last_id = TokenPayLoad.ID,
                        last_ip = ClientInfo.IP,
                        last_name = TokenPayLoad["username"],
                        last_time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
                    });
                }
            }
            #endregion
            #region Events
            foreach(dynamic item in update_events)
            {
                DB.QuickInsert(up, "EXTEND_SINGLETABLE_OP_EVENTS", new
                {
                    item.S_UID,
                    item.S_Event_No,
                    add_id = TokenPayLoad.ID,
                    add_ip = ClientInfo.IP,
                    add_name = TokenPayLoad["username"],
                    add_time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
                    last_id = TokenPayLoad.ID,
                    last_ip = ClientInfo.IP,
                    last_name = TokenPayLoad["username"],
                    last_time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
                });
            }
            #endregion
            CommitTrans();
            return new
            {
                code = "success",
                msg = "操作成功",
                uid = info.s_uid
            };
        }

        [EWRARoute("get", "/dynamicfunc/metalist")]
        [EWRARouteDesc("获取元数据表的栏位信息")]
        [EWRAOutputDesc("返回结果", @"{
result:[{
    metauid:'元数据表的uid',
    metaname:'元数据表名',
    metadesc:'元数据表描述',
    search_columns:[{
        column_name:'栏位名称',
        column_desc:'栏位描述',
        data_type:'数据类型'，
        sort_num:'排序编号,界面显示栏位会按照排序序号升序来显示',
        op_select_options:[允许使用的查询条件，like-模糊查询，=-精确查询，>-大于,>=-大于等于，<-小于，<=-小于等于]，
        memo:'栏位备注'
    }],
    columns:[{
        column_name:'栏位名称',
        column_desc:'栏位描述',
        data_type:'数据类型'，
        sort_num:'排序编号,界面显示栏位会按照排序序号升序来显示',
        memo:'栏位备注'
    }]
}]
}")]
        public List<object> GetMetaInfo()
        {
            SetCacheEnable(false);
            var up = DB.NewMetaUnitParameter();
            var s = from t in DB.LamdaTable(up, "EXTEND_METADATA", "a")
                    join t2 in DB.LamdaTable(up, "EXTEND_METADATA_COLUMNS", "b").LeftJoin() on t.metauid equals t2.metauid
                    where t.iscreated == 1 && t.islocked == 1
                    orderby t.metaname, t2.sortnum
                    select new
                    {
                        t.metauid,
                        t.metaname,
                        t.metadesc,
                        t.metacategoryno,
                        t.islocked,
                        t.iscreated,
                        t2.MetaColumnName,
                        t2.MetaColumnDesc,
                        t2.MetaDataType,
                        t2.MetaDataPrecision,
                        t2.MetaDataScale,
                        t2.MetaReference,
                        t2.MetaDataDefault,
                        t2.MetaAllowEmpty,
                        t2.MetaIsPK,
                        t2.SortNum,
                        t2.IsShow,
                        t2.Memo
                    };

            return (from t in s.GetQueryList(up)
                    group t by t.GetValue("metauid") into g
                    select new
                    {
                        metauid = g.First().GetValue("metauid"),
                        metaname = g.First().GetValue("metaname"),
                        metadesc = g.First().GetValue("metadesc"),

                        search_columns = g.Where(w => ComFunc.nvl(w.MetaColumnName) != "" && search_support_date_type.Contains(((string)ComFunc.nvl(w.MetaDataType)).ToLower()))
                                        .Select((tt) =>
                                        {
                                            var default_op_select_options = new List<dynamic>();
                                            default_op_select_options.Add(new { text = "模糊查询", value = "like" });
                                            default_op_select_options.Add(new { text = "精确查询", value = "=" });
                                            default_op_select_options.Add(new { text = "大于", value = ">" });
                                            default_op_select_options.Add(new { text = "大于等于", value = ">=" });
                                            default_op_select_options.Add(new { text = "小于", value = "<" });
                                            default_op_select_options.Add(new { text = "小于等于", value = "<=" });

                                            IEnumerable<object> op_select_options = default_op_select_options;
                                            //reference有值的时候只能使用精确查询
                                            if (ComFunc.nvl(tt.MetaReference) != "" && ComFunc.nvl(tt.MetaReference) != "{}")
                                            {
                                                op_select_options = default_op_select_options.Where(w => w.text == "精确查询");
                                            }
                                            //日期类型不可使用模糊查询
                                            if (ComFunc.nvl(tt.MetaDataType) == "datetime")
                                            {
                                                op_select_options = default_op_select_options.Where(w => w.text != "模糊查询");
                                            }
                                            return new
                                            {
                                                column_name = tt.GetValue("MetaColumnName"),
                                                column_desc = tt.GetValue("MetaColumnDesc"),
                                                data_type = tt.GetValue("MetaDataType"),
                                                sort_num = tt.GetValue("SortNum"),
                                                op_select_options,
                                                memo = tt.GetValue("Memo")
                                            };
                                        }),
                        columns = from tt in g
                                  where ComFunc.nvl(tt.MetaColumnName) != ""
                                  select new
                                  {
                                      column_name = tt.GetValue("MetaColumnName"),
                                      column_desc = tt.GetValue("MetaColumnDesc"),
                                      data_type = tt.GetValue("MetaDataType"),
                                      sort_num = tt.GetValue("SortNum"),
                                      memo = tt.GetValue("Memo")
                                  }
                    }).ToList<object>();

        }

    }
}
